package org.cnbi.web.system.listener;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cnbi.entity.Company;
import org.cnbi.entity.Compose;
import org.cnbi.entity.IndicatorExpression;
import org.cnbi.entity.Kemu;
import org.cnbi.entity.Menu;
import org.cnbi.entity.Role;
import org.cnbi.entity.Subject;
import org.cnbi.service.IHandleService;
import org.cnbi.utils.file.FileUtil;
import org.cnbi.utils.json.JsonFileUtil;
import org.cnbi.utils.license.LicenseUtil;
import org.cnbi.utils.pojo.MsgBean;
import org.cnbi.utils.pojo.SubjectSqlBean;
import org.cnbi.utils.pojo.UtilDim;
import org.cnbi.utils.pojo.XmlSqlBean;
import org.cnbi.utils.pojo.indicator.IndicatorParamsBean;
import org.cnbi.utils.string.StringUtil;
import org.cnbi.utils.tools.ActionConstants;
import org.cnbi.utils.tools.Constants;
import org.cnbi.utils.tools.GlobalConstants;
import org.cnbi.utils.tools.MenuConstants;
import org.cnbi.utils.tools.StateConstants;
import org.cnbi.utils.tools.SymbolConstants;
import org.cnbi.utils.xml.XMLUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
 * 工程初始类 Copyright © 2014中国经邦. All rights reserved.
 * 
 * @Author 龚佳新
 * @Time 2014年3月19日上午8:50:11
 */
public class WebApplicationInitializer implements ServletContextListener {
	private final static Log logger = LogFactory.getLog(WebApplicationInitializer.class);

	private ServletContext servletContext;
	/**
	 * 获取spring注入的bean对象
	 */
	private WebApplicationContext springContext;

	public IHandleService handleService;// dashboardService

	private Map<String, String> sqlMap = new HashMap<String, String>();
	
	Map<String, SubjectSqlBean> subjectMap = new HashMap<String, SubjectSqlBean>();

	private Map<String, List<UtilDim>> dimMap = new HashMap<String, List<UtilDim>>();
	
	private Map<Integer, List<IndicatorParamsBean>> indicatorParamsMap = new HashMap<Integer, List<IndicatorParamsBean>>();

	private String projectName;

	private String realPath;

	/**
	 * 系统
	 */
	public void contextDestroyed(ServletContextEvent contextEvent) {
		logger.info("【" + projectName + "】系统已经成功销毁了！");
	}

	public void contextInitialized(ServletContextEvent contextEvent) {
		this.servletContext = contextEvent.getServletContext();// sqlXmpName
		projectName = servletContext.getInitParameter("cnbi");
		String sqlXmpName = servletContext.getInitParameter(Constants.XMLSQLBEAN);
		realPath = this.servletContext.getRealPath(File.separator);
		springContext = WebApplicationContextUtils.getWebApplicationContext(contextEvent.getServletContext());
		handleService = (IHandleService) springContext.getBean("handleService"); // dashboardService
		initSql(sqlXmpName);
		initCompanyData();// ON_LINE_USERS
	
		queryMenuList();
		queryMenuTree();
		initDimData();
		initSubjectData();
		checkInvalid();
		initRoleData();
		initIndicatorData();
		initKemuData();//初始化科目列表
		readReportJson("json/report-help.json");
		logger.info("【" + projectName + "】系统已经成功启动了！并且也成功连接到数据库源！工程路径==" + realPath);

	}
	
	private void initIndicatorParams(){//
		 String idsSql = sqlMap.get(ActionConstants.INIT + Constants.EXPRESSION+"ids"),
		  sql = sqlMap.get(ActionConstants.INIT + Constants.EXPRESSION+ Constants.PARAMS);
		  indicatorParamsMap = handleService.queryIndicatorParamsMap(idsSql, sql);
		// System.out.println(JsonUtil.generateJson(indicatorParamsMap));
		  //把参数全部搞成sql模板 不弄了 想出了更好的办法
//		  for (Entry<Integer, List<IndicatorParamsBean>> entry: indicatorParamsMap.entrySet()) {
//			  Integer  key = entry.getKey();
//			    List<IndicatorParamsBean>  paramList = entry.getValue();
//			    for (IndicatorParamsBean bean :paramList) {
//					System.out.println(bean);
//				/*	formular = Fact("0001","${company},0&0,1200100","C")
//							 *      主题0001   公司100110  期间2013&1  项目1011  度量B*/
//					String []factArr = StringUtil.getFactFomularArray(bean.getExp());
//					SubjectSqlBean subject = subjectMap.get(factArr[0]);
//				}
//
//		  }
   }
	 
	private void setIndicatorParams(List<IndicatorExpression> indicatorList){
		for (IndicatorExpression bean : indicatorList){
  		    int id = bean.getId();
  		     List<IndicatorParamsBean> params = indicatorParamsMap.get(id);
  		    if(null != params && params.size() >0){
  		    	 List<IndicatorParamsBean> copyList=new ArrayList<IndicatorParamsBean>(Arrays.asList(new IndicatorParamsBean[params.size()]));
  		    	 java.util.Collections.copy(copyList, params);
  			     bean.setParams(copyList);
  		    }
  		   if(null != bean.getChildren() && bean.getChildren().size()> 0){
  			 setIndicatorParams(bean.getChildren());
  		   }
		}
	} 
    private void initIndicatorData(){
    	long a = System.currentTimeMillis();
    	initIndicatorParams();
    	String sql = sqlMap.get(ActionConstants.INIT + Constants.EXPRESSION),help="  and npid =:id order by csortby ";
    	List<IndicatorExpression> indicatorList = (List<IndicatorExpression>) handleService.queryIndicatorList(sql+help, new IndicatorExpression());
    	setIndicatorParams(indicatorList);
    	servletContext.setAttribute(MenuConstants.INDICATOR+StateConstants.LIST, indicatorList);
    	List<IndicatorExpression> indicatorListTemp = (List<IndicatorExpression>) handleService.query(sql+" and cisfolder='N'", new IndicatorExpression());
    	setIndicatorParams(indicatorListTemp);
    	Map<Integer,IndicatorExpression> map = new LinkedHashMap<Integer,IndicatorExpression>();
    	for (IndicatorExpression ii : indicatorListTemp) {
    		map.put(ii.getId(), ii);
    		//if(null != ii.getIndcode()){
    			//logger.info("------------------------>"+ii);
    		//}
		}
    	servletContext.setAttribute(MenuConstants.INDICATOR+StateConstants.MAP, map);
    	long b = System.currentTimeMillis();
    	logger.info("初始指标共用了"+(b-a)+"毫秒！");
    	//logger.info(JsonUtil.generateJson(indicatorList));
    }
	private void checkInvalid() {
		String sql = sqlMap.get(ActionConstants.INIT + Constants.LICENSE);
		LicenseUtil license = new LicenseUtil(sql, "properties/config");
		MsgBean msg = license.getMsgBean();
		Properties pro = license.getProps();
		if (StringUtil.isBlank(msg.getText())) {
			try {
				String errorMsg = "", phone = pro.getProperty("info.outtime");
				if (handleService.queryUserLicenseLastTimeWhetherPastdue(sql)) {
					errorMsg =pro.getProperty("info.outtime");
				}
				msg.setText(errorMsg + phone);
				logger.info("成功验证license文件！");
			} catch (Exception e) {
				logger.error("查询license文件是否已过期时出错了！\n" + e.getMessage());
			}
		}
		checkUrlIsInvalid("report.convertserviceurl",pro);
		servletContext.setAttribute(Constants.LICENSE_CHECK_INFO, license.getMsgBean());
		
	}
	private void checkUrlIsInvalid(String key,Properties pro){
		String url = pro.getProperty(key);//report.info
		MsgBean checkUrlIsInvalidMsg = new MsgBean(false);
		if(!FileUtil.checkUrlIsInvalid(url)){
			String msg = pro.getProperty("report.info").replace(key,url);
			logger.error(msg);
			checkUrlIsInvalidMsg.setText(msg);
		}else{
			 checkUrlIsInvalidMsg.setFlag(true);
			 checkUrlIsInvalidMsg.setText(url);
		}
		servletContext.setAttribute(GlobalConstants.CONFIGFILE,checkUrlIsInvalidMsg);
	}

	/**
	 * 初始所有维度数据
	 * 
	 * @Author 龚佳新
	 * @Time 2014年3月21日下午6:12:09
	 */
	private void initDimData() {
		String dimSql = sqlMap.get(ActionConstants.INIT + Constants.DIM), dimFieldSql = sqlMap.get(ActionConstants.INIT + Constants.DIM + Constants.FIELD);
		String raplaceStr = GlobalConstants.DIMHELP;
		try {
			@SuppressWarnings("unchecked")
			List<UtilDim> dimDatas = (List<UtilDim>) handleService.query(dimSql, new UtilDim());
			for (int i = 0, len = dimDatas.size(); i < len; i++) {// factTable
				UtilDim mapBean = dimDatas.get(i);
				String factTable = mapBean.getScode(), sql = sqlMap.get(ActionConstants.INIT + Constants.ITEM);
				String fieldKey = factTable.replace(raplaceStr, "");
				if(!dimMap.containsKey(fieldKey)){
					sql = sql.replace(":factTable", factTable);
					if(!factTable.contains("DW_DimItem")){
						sql = sql.replace(",nlevel as level", "");
					}
					@SuppressWarnings("unchecked")
					List<UtilDim> dimList = (List<UtilDim>) handleService.query(sql, new UtilDim());
					if(factTable.contains("DW_DimItem")){
						for(UtilDim table:dimList){
							if(table.getLevel() == 1){
							}
						}
					}
					System.out.println("fieldKey==="+fieldKey);
					dimMap.put(fieldKey, dimList);
				}
			}
			 servletContext.setAttribute(Constants.DIM + StateConstants.MAP, dimMap);

			@SuppressWarnings("unchecked")
			List<UtilDim> dimFieldDatas = (List<UtilDim>) handleService.query(dimFieldSql, new UtilDim());
			Map<String, String> dimFieldMap = new HashMap<String, String>();
			for (int i = 0, len = dimFieldDatas.size(); i < len; i++) {// factTable
				UtilDim mapBean = dimFieldDatas.get(i);
				dimFieldMap.put(mapBean.getScode(), mapBean.getSname());
			}
			servletContext.setAttribute(Constants.DIM + Constants.FIELD + StateConstants.MAP, dimFieldMap);
		} catch (Exception e) {
			logger.error("初始initDimData所有维度数据时出错了！\n" + e);
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
	}

	/**
	 * 初始所有主题维度数据
	 */
	private void initSubjectData() {
		String subKey = ActionConstants.INIT + Constants.SUBJECT + StateConstants.LIST, comKey = ActionConstants.INIT + Constants.COMPOSE + StateConstants.LIST, subSql = sqlMap.get(subKey), comSql = sqlMap.get(comKey);// ,dimItemDatasSql
		// String filePath = realPath+"resources"+File.separator+"json"+File.separator;
		try {//
			@SuppressWarnings("unchecked")
			List<Subject> subjectList = (List<Subject>) handleService.query(subSql, new Subject("0001", "所有主题", "0"));
			for (int i = 0, len = subjectList.size(); i < len; i++) {
				Subject subject = subjectList.get(i);
				@SuppressWarnings("unchecked")
				List<Compose> composeList = (List<Compose>) handleService.query(comSql, new Compose(subject.getScode()));
				Map<String, String> measureMap = null;//
				Map<String, Compose> compseMap = null;
				for (int j = 0, lj = composeList.size(); j < lj; j++) {
					Compose compose = composeList.get(j);
					String type = compose.getType();// 类型
					if (type.equalsIgnoreCase(Constants.MEASURE)) {// 度量
						if (null == measureMap) {// 有节约资源哦 亲！能不new的就坚决不new
							measureMap = new TreeMap<String, String>(new Comparator<String>() {// 降序排序obj2.compareTo(obj1);
										public int compare(String obj1, String obj2) {
											return obj1.compareTo(obj2);
										}
									});
						}
						measureMap.put(compose.getField(), compose.getSname());
						servletContext.setAttribute(Constants.SUBJECT + subject.getScode(), measureMap);
					} else if (type.equalsIgnoreCase(Constants.SUB)) {// SUBJECT 主题

					} else {// 维度
						if (null == compseMap) {// 原理同上
							compseMap = new HashMap<String, Compose>();
						}
						compose.setDimDatas(dimMap.get(compose.getField()));
						compseMap.put(compose.getField(), compose);
					}
				}
				if (null != compseMap && null != measureMap) {
					SubjectSqlBean subjectBean = new SubjectSqlBean(subject, compseMap, measureMap);
					subjectMap.put(subject.getScode(), subjectBean);
					// logger.info(subject.getSname() + "【" + subject.getScode()
					// + "】议题SQL====\n" + subjectBean.getSql());
					 if (subject.getScode().equals("0001")) {
					   //System.out.println(subjectBean.getSql(new DisplayBean(true,true)));
					 //querySubjectData(subjectBean,filePath+subject.getScode()+"22.json");
					 }
				}
			}
			servletContext.setAttribute(Constants.SUBJECT + StateConstants.MAP, subjectMap);
		} catch (Exception e) {
			logger.error("初始初始所有维度数据时出错了！\n" + e);
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
	}
	
	private String getPath(String filePath){
		filePath = StringUtil.replace(filePath, "classpath:", "").replace("/", "\\");
		filePath = realPath+"WEB-INF\\classes\\"+filePath;
		return filePath;
	}
	
	private void readReportJson(String filePath){
		filePath = getPath(filePath);
		String json = new JsonFileUtil().readJsonFile(filePath);
		json = StringUtil.replaceBlank(json);
		//DimHelpBean bean = (DimHelpBean)JsonUtil.conventString2Bean(json,DimHelpBean.class);
		//json = JsonUtil.generateJson(bean);
		servletContext.setAttribute("reportJson",json);
	}

	/**
	 * 初始化sql语句的xml文件
	 * 
	 * @param filePath
	 *            目录 以分号分割 WEB-INF\classes
	 */
	private void initSql(String filePath){
		//filePath = StringUtil.replace(filePath, "classpath:", "").replace("/", "\\");
		//filePath = realPath+"WEB-INF\\classes\\"+filePath;
		filePath = getPath(filePath);
		int index = filePath.lastIndexOf("\\")+1;
		String fileRealPath = filePath.substring(0, index), 
				prefix = filePath.substring(index, filePath.length());
		File [] files = new File(fileRealPath).listFiles();
		String []temp = prefix.split("\\"+SymbolConstants.MIDDLELINE);
		String splitFileName = temp[0]+SymbolConstants.MIDDLELINE;
		boolean flag = false;
		if(temp.length == 2 && temp[1].equals(SymbolConstants.STAR)){
			flag = true;
		} 
		for(int i=0,len = files.length;i<len;i++){
			String fileName = files[i].getName(), keyName = fileName.replace(".xml", "");
			if(prefix.length() == 0 || prefix.equals(SymbolConstants.STAR)|| flag == true || fileName.contains(prefix)){
				if(flag && !fileName.contains(splitFileName)){}else{
					    XmlSqlBean beans = XMLUtils.getConfigXmlBean(files[i]);
						XMLUtils.getConfigXmlMap(sqlMap, beans);
						servletContext.setAttribute(keyName, beans);
						logger.info("加载了"+fileName+"文件>>"+beans.getName());
				}
				 
			}
		}
		servletContext.setAttribute(Constants.SQLMAP, sqlMap);
	
	}

	/**
	 * @param filePath  老的方法
	 */
//	private void initSqls(String filePath) {
//		try {
//			String files[] = filePath.split("\\" + Constants.SEMICOLON);
//			for (int a = 0, len = files.length; a < len; a++){
//				String fileName = files[a], keyName = fileName.replace(".xml", "");
//				XmlSqlBean beans = XMLUtils.getConfigXmlBean(fileName);
//				XMLUtils.getConfigXmlMap(sqlMap, beans);
//				servletContext.setAttribute(keyName, beans);
//				logger.info("加载了"+fileName+"文件>>"+beans.getName());
//			}
//			servletContext.setAttribute(Constants.SQLMAP, sqlMap);
//		} catch (Exception e) {
//			logger.error("初始sql语句时出错了！\n" + e);
//			throw new RuntimeException(e.getMessage(), e.getCause());
//		}
//	}

	/**
	 * 查询所有菜单
	 * 
	 * @return
	 */
	private void queryMenuList() {
		String key =ActionConstants.INIT+MenuConstants.MENU;
		String sql = sqlMap.get(key);
		try {
			@SuppressWarnings("unchecked")
			List<Menu> menuList = (List<Menu>) handleService.query(sql, new Menu());
			servletContext.setAttribute(key, menuList);
		} catch (Exception e) {
			logger.error("查询所有菜单时出错了！\n" + sql + "--\n" + e);
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
	}
	private void queryMenuTree(){
		String key =ActionConstants.INIT+MenuConstants.MENU+MenuConstants.TREE;
		String sql = sqlMap.get(key);
		try {
			Menu menuTree = (Menu) handleService.queryMenuTree(sql, new Menu("0","所有菜单"));
			servletContext.setAttribute(MenuConstants.MENU+MenuConstants.TREE, menuTree);
		} catch (Exception e) {
			logger.error("查询所有菜单时出错了！\n" + sql + "--\n" + e);
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
	}
	
	 //初始化科目数据
	 @SuppressWarnings("unchecked")
	private void initKemuData() {
		String sqlAll = sqlMap.get(MenuConstants.KEMU + StateConstants.LIST);
		try {
			List<Kemu> kemusList = (List<Kemu>) handleService.query(sqlAll,new Kemu());
			servletContext.setAttribute(MenuConstants.KEMU+StateConstants.LIST, kemusList);
		} catch (Exception e) {
			logger.error("查询所有科目类别时出错了！\n" + sqlAll + "--\n" + e);
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
		 //类别
		String sqlStype = sqlMap.get(ActionConstants.INIT + MenuConstants.KEMU);
		String sqlKemuChild = sqlMap.get(ActionConstants.INIT + MenuConstants.KEMU+MenuConstants.TREE);
		List<Kemu>  kemus = null;
		try{
			kemus = (List<Kemu>) handleService.query(sqlStype, new Kemu());
		}catch(Exception e){
			logger.error("查询科目类别时出错了！\n" + sqlStype + "--\n" + e);
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
		List<Kemu> kemuList = new ArrayList<Kemu>();
		if(kemus!= null && kemus.size() !=0 ){//存在科目类别
			for (int i = 0; i < kemus.size(); i++) {
				Kemu kemu = kemus.get(i);
				kemu.setScode("");
				try {
					Kemu kemutree = (Kemu)handleService.queryMenuTree(sqlKemuChild, kemu);
					kemuList.add(kemutree);
					servletContext.setAttribute(MenuConstants.KEMU + MenuConstants.TREE + StateConstants.LIST, kemuList);
				} catch (Exception e) {
					logger.error("查询类别科目下的子科目时出错了！\n" + sqlKemuChild + "--\n" + e);
					throw new RuntimeException(e.getMessage(), e.getCause());
				}
			}
		}
	}
	 

	// private void queryDashboardList(){
	// String key = Constants.DASH + Constants.LIST;
	// String sql = sqlMap.get(key);
	// try {
	// List<Dashboard> dashList = dashboardService.queryAllDashboard(sql, new
	// Dashboard());
	// servletContext.setAttribute(key, dashList);
	// } catch (Exception e) {
	// logger.error("查询所有dashboard时出错了！---->\n" + sql + "\n" + e);
	// e.printStackTrace();
	// throw new RuntimeException(e.getMessage(), e.getCause());
	// }
	// }
	/**
	 * 查询所有模型
	 * 
	 * @return scode, sname,spcode,isleaf,isactive,state
	 */
	// private void queryDashboardTree() {
	// String key = Constants.DASH + Constants.BEAN;
	// String sql = sqlMap.get(key);
	// try {
	// // Class.forName(Dashboard.class);
	// // Class c = Class.forName(“A”);factory =
	// // (AInterface)c.newInstance();
	// Dashboard ss = new Dashboard("0", "所有模型", "", 0, 0);
	// // ss = (Dashboard)Class.newInstance();
	// Dashboard bean = dashboardService.queryDashboardTree(sql, ss);
	// servletContext.setAttribute(key, bean);
	// } catch (Exception e) {
	// logger.error("查询所有菜单时出错了！---->\n" + sql + "\n" + e);
	// throw new RuntimeException(e.getMessage(), e.getCause());
	// }
	// }

	/**
	 * 初始所有公司
	 */
	private void initCompanyData(){
		String key =ActionConstants.INIT+Constants.COMPANY+StateConstants.LIST;
		String sql = sqlMap.get(key);
		List<Company> list = (List<Company>) handleService.query(sql, new Company());
		Map<String,Company> map = new HashMap<String,Company>();
		for (int i = 0; i < list.size(); i++) {
			Company company = list.get(i);
			if(null == company.getRanges())company.setRanges("1");
			if(null == company.getType())company.setType("z");
			map.put(company.getScode(),company);
		}
		servletContext.setAttribute(Constants.COMPANY+StateConstants.LIST, list);
		servletContext.setAttribute(Constants.COMPANY+StateConstants.MAP, map);
	}
	
	/**
	 * 初始化 角色 信息
	 * */
	private void initRoleData() {
		String key = ActionConstants.INIT+Constants.ROLE+StateConstants.LIST;
		String sql = sqlMap.get(key);
		List<Role> list = (List<Role>) handleService.query(sql, new Role());
		Map<String,String> map = new HashMap<String, String>();
		for (int i = 0; i < list.size(); i++) {
			Role role = list.get(i);
			map.put(String.valueOf(role.getRoleID()),role.getSroleName());
		}
		servletContext.setAttribute(Constants.ROLE+StateConstants.LIST, list);
		servletContext.setAttribute(Constants.ROLE+StateConstants.MAP, map);
	}
}
